/**
 * 按键消抖模块
 * 通过打两拍,查看2拍的数值差异知道按键按下,让计数器递减到0作为稳定z状态方式进行消抖
 */
module KeyDebounce(
        input clk,
        input rst_n,
        // 这里是按键的输入,是个不稳定的信号,会有脉冲抖动
        input key_in,
        output reg key_out
    );

    // 需要消抖的时间,单位为时钟周期,50Mhz时钟下20ms约等于1_000_000个周期
    parameter DEBOUNCE_TIME = 32'd1_000_000;
    reg [31:0] debounce_cnt;

    // 对输入的按键打2拍消抖
    reg key0, key1;

    // 进行打拍消抖
    always @ (posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            key0 <= 1'b1;
            key1 <= 1'b1;
        end
        else begin
            key0 <= key_in;
            key1 <= key0;
        end
    end

    // 对打拍后的按键进行计数
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // 默认为0
            debounce_cnt <= 0;
        end
        else begin
            // 当打拍后的值不同时,重新计数
            if(key0 != key1) begin
                debounce_cnt <= DEBOUNCE_TIME;
            end
            else if (debounce_cnt > 0) begin
                debounce_cnt <= debounce_cnt - 1;
            end
            else
                debounce_cnt <= 0;
        end
    end

    // 进行计数消抖输出稳定信号
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            key_out <= 1'b1;
        end
        else begin
            if (debounce_cnt == 1) begin
                // 减到1时,说明已经稳定了,翻转输出
                key_out <= key1;
            end
            else begin
                key_out <= key_out;
            end
        end
    end

endmodule
